<template>
	<a-popover
		v-bind="$attrs"
		trigger="click"
		class="color-picker"
		:visible="showPicker"
		:getPopupContainer="getPopupContainer"
		:class="[colorSize ? 'color-picker--' + colorSize : '']"
	>
		<template #content>
			<div class="color-dropdown__main-wrapper">
				<SvPanel ref="svPanel" :color="color" />
				<HueSlider ref="hue" class="hue-slider" :color="color" vertical />
			</div>
			<AlphaSlider v-show="props.showAlpha" ref="alpha" :color="color" />
			<preDefine
				v-show="predefine.length"
				ref="predefine"
				:color="color"
				:colors="predefine"
			/>
			<div class="color-dropdown__btns">
				<span class="color-dropdown__value">
					<a-input
						v-model:value="customInput"
						size="small"
						@pressEnter="handleConfirm"
						@blur="handleConfirm"
					/>
				</span>
				<div class="dropdown__btns">
					<a-button size="small" class="cancel-button" @click="clear"
						>取消</a-button
					>
					<a-button type="primary" size="small" @click="confirmValue"
						>确定</a-button
					>
				</div>
			</div>
		</template>
		<span class="color-picker__trigger" @click="handleTrigger">
			<span class="color-picker__color" :class="{ 'is-alpha': showAlpha }">
				<span
					class="color-picker__color-inner"
					:style="{
						backgroundColor: color.value,
					}"
				>
					<DownOutlined
						v-show="value || showPanelColor"
						style="color: #909399"
					/>
					<CloseOutlined
						v-if="!value && !showPanelColor"
						style="color: #909399"
					/>
				</span>
			</span>
		</span>
	</a-popover>
</template>
<script setup lang="ts">
import AlphaSlider from './components/alpha-slider.vue';
import HueSlider from './components/hue-slider.vue';
import SvPanel from './components/sv-panel.vue';
import preDefine from './components/pre-define.vue';
import { CloseOutlined, DownOutlined } from '@ant-design/icons-vue';
import { IEvent } from '@/core';
import debounce from 'lodash/debounce';
import Color from './util/color';
import { IUseOptions, OPTIONS_KEY, ColorPickerProps } from './color-picker';

type eventType = 'valueChange' | 'activeChange';

interface EditorEmit {
	(name: 'component-action', value: IEvent<eventType>): void;
}
const props = defineProps(ColorPickerProps);
const emit = defineEmits<EditorEmit>();
/**
 * popover 显示状态
 */
let showPicker = ref(false);
/**
 * setShowPicker事件
 * @param value
 */
const setShowPicker = (value: any) => {
	showPicker.value = value;
};
const debounceSetShowPicker = debounce(setShowPicker, 50);
/**
 * 区分popover的关闭是通过点击body关闭的还是通过按钮、输入框关闭的
 */
const hasClickBtn = ref<boolean>(false);
const showAlpha = ref<boolean>(true); //管理透明度条
const hue = ref<any>(null); //管理HueSlider
const svPanel = ref<any>(null); //管理SvPanel
const alpha = ref<any>(null); //管理AlphaSlider
const showPanelColor = ref(false); //管理显示面板
const customInput = ref<any>(''); //定义输入框

/**
 * new Color
 */
const color: Color = reactive(
	new Color({
		enableAlpha: props.showAlpha,
		format: props.showAlpha ? 'rgb' : props.colorFormat,
	})
);

/**
 * 选择器大小
 */
const colorSize = computed(() => {
	return props.size;
});

/**
 * 选择器启动
 */
const colorDisabled = computed(() => {
	return props.disabled;
});

/**
 * 计算当前颜色的#十六进制值
 */
const currentColor = computed(() => {
	return !props.value && !showPanelColor.value ? '' : color.value;
});

/**
 * 监听value值
 */
watch(
	() => props.value,
	(newVal: string) => {
		if (!newVal) {
			showPanelColor.value = false;
		} else if (newVal && newVal !== color.value) {
			color.fromString(newVal);
		}
	}
);

/**
 * 监听转换后的十六进制值
 */
watch(
	() => currentColor.value,
	(val: string) => {
		customInput.value = val;
		doEditorEmit('activeChange', val);
	}
);
/**
 * 监听颜色值
 */
watch(
	() => color.value,
	() => {
		if (!props.value && !showPanelColor.value) {
			showPanelColor.value = true;
		}
	}
);

/**
 * 监听选择器控制值
 */
watch(
	() => showPicker.value,
	(newVal: boolean) => {
		if (newVal) {
			hasClickBtn.value = false;
		} else {
			if (!hasClickBtn.value) {
				hide();
			}
		}
		setTimeout(() => {
			hue.value?.update();
			svPanel.value?.update();
			alpha.value?.update();
		}, 100);
	}
);

/**
 * hide事件
 */
const hide = () => {
	debounceSetShowPicker(false);
	resetColor();
};

/**
 * resetColor事件
 */
const resetColor = () => {
	nextTick(() => {
		if (props.value) {
			color.fromString(props.value);
		} else {
			showPanelColor.value = false;
		}
	});
};

/**
 * handleTrigger触发事件
 */
const handleTrigger = () => {
	if (colorDisabled.value) return;
	debounceSetShowPicker(!showPicker.value);
};

/**
 * 失去焦点确认事件
 */
const handleConfirm = () => {
	color.fromString(customInput.value);
};

/**
 * 确定值
 */
const confirmValue = () => {
	hasClickBtn.value = true;
	const colorValue = color.value;
	doEditorEmit('valueChange', colorValue);
	debounceSetShowPicker(false);
	nextTick(() => {
		const newColor = new Color({
			enableAlpha: props.showAlpha,
			format: props.showAlpha ? 'rgb' : props.colorFormat,
		});
		newColor.fromString(props.value);
		if (!color.compare(newColor)) {
			resetColor();
		}
	});
	showPicker.value = false;
	return colorValue;
};

/**
 * 取消(清除)值
 */
const clear = () => {
	color.value = '';
	hasClickBtn.value = true;
	debounceSetShowPicker(false);
	resetColor();
	showAlpha.value = false;
	showPicker.value = false;
};

/**
 * 获取popover容器
 */
const getPopupContainer = (triggerNode: HTMLElement) => {
	return triggerNode.parentElement;
};

/**
 * 处理编辑器抛值
 */
const doEditorEmit = (action: eventType, value: any) => {
	emit('component-action', {
		name: props.name,
		action: action,
		data: value,
	});
};

onMounted(() => {
	clear();
	if (props.value) {
		color.fromString(props.value);
		customInput.value = currentColor.value;
	}
});

provide<IUseOptions>(OPTIONS_KEY, {
	currentColor,
});
</script>
